#include <GL/glew.h>
#include "entityEngine.h"
#include "modelManager.h"
#include "textureManager.h"
#include "shaderManager.h"
#include "materialManager.h"
entity::entity(std::string modelID)
{
	this->modelID = modelID;
	xPos = 0;
	yPos = 0;
	zPos = 0;
	xRot = 0;
	yRot = 0;
	zRot = 0;
	billboard=false;
	globalMaterial="";
}

entity::entity(float xSca, float ySca)
{
	this->modelID = "";
	xPos = 0;
	yPos = 0;
	zPos = 0;
	xRot = 0;
	yRot = 0;
	zRot = 0;
	this->xSca = xSca;
	this->ySca = ySca;
	billboard=true;
}
void entity::setGlobalMaterial(std::string materialName)
{
	globalMaterial = materialName;
}
void entity::disableGlobalMaterial()
{
	globalMaterial = "";
}
void entity::display()
{
	if(billboard)
	{
		

			glEnable(GL_BLEND);
			glDepthMask(GL_FALSE); //http://www.cse.msu.edu/~cse472/transparency.html
					glPushMatrix();
			
					glTranslated(xPos, yPos, zPos);
					billboardCheatSphericalBegin();

					glScaled(xSca,ySca, 0);
					glBegin(GL_QUADS);
						glTexCoord2f(0.0f,0.0f); glVertex3f(.5f,-.5f,0.0f);
						glTexCoord2f(0.0f,1.0f); glVertex3f(.5f,.5f,0.0f);
						glTexCoord2f(1.0f,1.0f); glVertex3f(-.5f,.5f,0.0f);
						glTexCoord2f(1.0f,0.0f); glVertex3f(-.5f,-.5f,0.0f);
					glEnd();
				glPopMatrix();
			billboardEnd();

		glDepthMask(GL_TRUE);

	}else{
		for(int x=0; x<MM()->getNumMatGroups(modelID); x++)
		{
			std::string MATNAME = MM()->getMatName(modelID, x);
			std::string MAT;
			if(globalMaterial.compare("") != 0)
				MAT = globalMaterial; //if a global material is specified use that instead.
			else
				MAT = MATNAME;

			mat* m = MATM()->getMaterial(MAT);
			if(m)
			{
				glColor4f(1.0f,1.0f,1.0f,1.0f);
				TM()->setTexture(m->texID);
				if(m->shaderID.compare("NOSHADER") != 0)
				{
					SM()->startShader(m->shaderID);
					for(int x=0; x<m->shaderVariables.size(); x++)
					{
						SM()->setFloat(m->shaderID,m->shaderVariables[x]->variable,m->shaderVariables[x]->value);
					}
				}
			}else{
				std::cout << "Error, could not find material " << MATNAME << "\n";
				TM()->setTexture("white.png");
			}

			MM()->displayModel(modelID, xPos, yPos, zPos, xRot, yRot, zRot,MATNAME);

			if(m)
			{
				if(m->shaderID.compare("NOSHADER") != 0)
					SM()->stopShader(m->shaderID);
			}
		}
	}

}

void entity::setPosition(float xPos, float yPos, float zPos)
{
	this->xPos = xPos;
	this->yPos = yPos;
	this->zPos = zPos;
}

void entity::setRotation(float xRot, float yRot, float zRot)
{
	this->xRot = xRot;
	this->yRot = yRot;
	this->zRot = zRot;
}

void entity::rotate(float xVel, float yVel, float zVel)
{
	this->xRot+=xVel;
	this->yRot+=yVel;
	this->zRot+=zVel;
}
void entity::translate(float xVel, float yVel, float zVel)
{
	this->xPos+=xVel;
	this->yPos+=yVel;
	this->zPos+=zVel;
}



void billboardCheatSphericalBegin() {
	
	float modelview[16];
	int i,j;

	// save the current modelview matrix
	glPushMatrix();

	// get the current modelview matrix
	glGetFloatv(GL_MODELVIEW_MATRIX , modelview);

	// undo all rotations
	// beware all scaling is lost as well 
	for( i=0; i<3; i++ ) 
	    for( j=0; j<3; j++ ) {
		if ( i==j )
		    modelview[i*4+j] = 1.0;
		else
		    modelview[i*4+j] = 0.0;
	    }

	// set the modelview with no rotations
	glLoadMatrixf(modelview);
}



void billboardEnd() {

	// restore the previously 
	// stored modelview matrix
	glPopMatrix();
}